package com.android.gallery3d.ui;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.net.Uri;
import android.os.Handler;

import com.android.gallery3d.app.AbstractGalleryActivity;
import com.android.gallery3d.app.PhotoPage;
import com.android.gallery3d.common.Utils;
import com.android.gallery3d.gifdecoder.GifBitmapProvider;
import com.android.gallery3d.gifdecoder.GifDecoder;
import com.android.gallery3d.gifdecoder.GifHeader;
import com.android.gallery3d.gifdecoder.GifHeaderParser;
import com.android.gallery3d.glrenderer.BitmapTexture;
import com.android.gallery3d.glrenderer.GLCanvas;
import com.android.photos.data.GalleryBitmapPool;

import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class GifScreenNail implements ScreenNail {
    private static final String TAG = "GifScreenNail";
    private Bitmap mBitmap;
    private GifScreenView mGifScreen;
    private int mHeight;
    private int mWidth;

    private Handler mHandler;
    private AbstractGalleryActivity mActivity;
    private PhotoPage mPhotoPage;

    public GifScreenNail(Bitmap bitmap, AbstractGalleryActivity activity, Uri uri) {
        mBitmap = bitmap;
        mActivity = activity;
        mWidth = mBitmap.getWidth();
        mHeight = mBitmap.getHeight();

        mGifScreen = new GifScreenView(activity.getApplicationContext(), uri, bitmap);
        mHandler = new Handler(activity.getMainLooper());
        mPhotoPage = (PhotoPage) mActivity.getStateManager().getTopState();
    }

    private static void recycleBitmap(Bitmap bitmap) {
        if (bitmap == null) return;
        GalleryBitmapPool.getInstance().put(bitmap);
    }

    public void draw(GLCanvas canvas, int x, int y, int width, int height) {
        mGifScreen.draw(canvas, x, y, width, height);
    }

    public void draw(GLCanvas canvas, RectF source, RectF dest) {
        mGifScreen.draw(canvas, source, dest);
    }

    public int getHeight() {
        return mHeight;
    }

    public int getWidth() {
        return mWidth;
    }

    public boolean isAnimating() {
        return false;
    }

    public boolean isGifPic() {
        return mGifScreen.isGifPic();
    }

    public void noDraw() {
    }

    public void recycle() {
        if (mGifScreen != null) {
            mGifScreen.recycle();
            mGifScreen = null;
        }
        recycleBitmap(mBitmap);
        mBitmap = null;
    }

    private class GifScreenView {
        private Canvas mCanvas;
        private Paint mPaint;
        private Context mContext;
        private BitmapTexture mTexture;
        private Bitmap mUploadBitmap;
        private GifDecoder mGifDecoder;

        public GifScreenView(Context context, Uri uri, Bitmap bitmap) {
            mContext = context;
            if (uri == null)
                throw new IllegalArgumentException("uri cannot be null");

            mGifDecoder = new GifDecoder(new GifBitmapProvider());
            InputStream inputStream = null;
            try {
                inputStream = mContext.getContentResolver().openInputStream(uri);
                byte[] data = isToBytes(inputStream);
                GifHeaderParser headerParser = new GifHeaderParser();
                headerParser.setData(data);
                GifHeader header = headerParser.parseHeader();
                mGifDecoder.setData(header, data);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                Utils.closeSilently(inputStream);
            }

            mUploadBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), getConfig(bitmap));
            mCanvas = new Canvas(mUploadBitmap);
            mPaint = new Paint();
            mCanvas.drawBitmap(bitmap, 0.0F, 0.0F, null);
            mTexture = new BitmapTexture(mUploadBitmap);
        }

        public byte[] isToBytes(InputStream is) throws IOException {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int read;
            try {
                while ((read = is.read(buffer)) != -1) {
                    os.write(buffer, 0, read);
                }
            } finally {
                is.close();
            }
            return os.toByteArray();
        }

        private Bitmap.Config getConfig(Bitmap bitmap) {
            Bitmap.Config config = bitmap.getConfig();
            if (config == null) {
                config = Bitmap.Config.ARGB_8888;
            }
            return config;
        }

        protected void draw(Canvas canvas) {
            canvas.drawColor(-1);
            mGifDecoder.advance();
            Bitmap bitmap = mGifDecoder.getNextFrame();
            int width = bitmap.getWidth();
            int height = bitmap.getHeight();
            int w = canvas.getWidth();
            int h = canvas.getHeight();
            canvas.save();
            canvas.drawBitmap(bitmap, (w - width) / 2, (h - height) / 2, mPaint);
            canvas.restore();

            int delay = mGifDecoder.getNextDelay();
            if (delay == 0) delay = 50;
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mPhotoPage.invalidatePhotoView();
                }
            }, delay);
        }

        public void draw(GLCanvas canvas, int x, int y, int w, int h) {
            if (mTexture != null)
                mTexture.yield();
            draw(mCanvas);
            if (mTexture != null)
                mTexture.draw(canvas, x, y, w, h);
        }

        public void draw(GLCanvas canvas, RectF source, RectF dest) {
            if (mTexture != null)
                mTexture.yield();
            draw(mCanvas);
            if (mTexture != null)
                mTexture.draw(canvas, source, dest);
        }

        public boolean isGifPic() {
            return true;
        }

        public void recycle() {
            if (mTexture != null) {
                mTexture.recycle();
                mTexture = null;
            }
            if (mUploadBitmap != null) {
                mUploadBitmap.recycle();
                mUploadBitmap = null;
            }
            mCanvas = null;
            mGifDecoder.clear();
            mHandler.removeCallbacksAndMessages(null);
        }
    }
}